﻿using System;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using WYJ.Log.UnitTests;

namespace WYJ.Log.LogWriters
{
    /// <summary>
    /// 待抽离到其它库中。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class LinePassage<T>
    {
        private readonly Debugger debugger;

        protected ChannelReader<T>? _reader;
        protected ChannelWriter<T>? _writer;
        private CancellationTokenSource _readerTokenSource = new CancellationTokenSource();
        protected bool disposedValue;

        protected LinePassage(Channel<T> channel)
        {
            _reader = channel.Reader;
            _writer = channel.Writer;
            debugger = new Debugger(this.GetType());
            ReadAsync(_readerTokenSource);
        }
        public async void WriteAsync(T message)
        {
            if (_writer == null) { return; }
            int retry = 1;
            debugger.WriteLine($"写入{message} 开始。");
            while (await _writer.WaitToWriteAsync().ConfigureAwait(false))
            {
                debugger.WriteLine($"写入{message} 正在进行...");

                if (_writer.TryWrite(message))
                {
                    debugger.WriteLine($"写入{message} 成功。");
                    break;
                }
                else
                {
                    debugger.WriteLine($"写入{message}  失败 {retry} 次");
                    retry++;
                }
            }
            debugger.WriteLine($"写入{message} 结束。");
        }


        /// <summary>
        /// 暂停消费
        /// </summary>
        public void Pause()
        {
            _readerTokenSource.Cancel();
            debugger.WriteLine($"Paused");
        }

        /// <summary>
        /// 启动消费
        /// </summary>
        public void Resume()
        {
            if (_readerTokenSource.IsCancellationRequested)
            {
                _readerTokenSource = new CancellationTokenSource();
                ReadAsync(_readerTokenSource);
            }
            else
            {
                debugger.WriteLine("Not need Resume");
            }
        }

        private async void ReadAsync(CancellationTokenSource _readerTokenSource)
        {
            if (_reader == null) { return; }
            debugger.Next();
            debugger.WriteTag("reader","Activated");
            var reader = _reader;
            while (await reader.WaitToReadAsync() && !_readerTokenSource.IsCancellationRequested)
            {
                debugger.WriteTag("reader", "WaitToReadAsync");
                T message = await reader.ReadAsync();
                debugger.WriteTag("reader", "Readed");
                await Next(message);
            }
            if (disposedValue)
            {
                DisposeReader();
                debugger.WriteTag("reader","已将 reader 释放");

            }
            debugger.WriteTag("reader", "Exited");
        }



        protected virtual Task Next(T msg)
        {
            Console.WriteLine(msg);
            return Task.CompletedTask;
        }


        private void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    DisposeWriter();
                    debugger.WriteLine("已将 writer 释放");
                }
                disposedValue = true;
            }
        }

        protected virtual void DisposeWriter()
        {
            _writer?.Complete();
            _writer = null;
        }
        protected virtual void DisposeReader()
        {
            _reader = null;
        }
        public void Dispose()
        {
            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }


    }
}